from django.core.exceptions import ObjectDoesNotExist
from django.db.models import Count
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import GenericViewSet
from auto_dj_test import pagination
from auto_dj_test.auth import RedisTokenAuthentication, RedisPermission
from aweirunner import models, serializers
from aweirunner.dto.tree_dto import TreeUpdateIn, TreeUniqueIn, TreeOut
from aweirunner.utils.day import get_day, get_week_format, get_month_format
from aweirunner.utils.decorator import request_log
from aweirunner.utils import response, prepare, day
from auto_dj_test.conf.MyLogger import MyLogger
from aweirunner.services.tree_service_impl import tree_service
from aweirunner.utils.response import StandResponse

logger = MyLogger(__name__).logger


class ProjectView(GenericViewSet):
    """
    项目增删改查
    GenericViewSet
        queryset： 用于指定默认的查询集，表示从数据库中获取的对象集合。

        serializer_class： 指定了使用的序列化器类，负责将模型实例转换为 JSON 格式（序列化）或从请求数据中反序列化创建模型实例。

        pagination_class： 指定了分页的类，控制 API 返回的数据量，避免一次性返回大量数据。
    """

    # 获取所有项目，通过更新时间进行排序
    queryset = models.Project.objects.all().order_by("-update_time")
    # 使用自定义的序列化器，这里的作用就是将模型实例序列化转换为JSON格式
    serializer_class = serializers.ProjectSerializer
    # 指定了分页的类，用于控制API返回的数量
    pagination_class = pagination.MyCursorPagination


    def list(self, request):

        projects = self.get_queryset()
        # 对查询集进行分页处理
        page_projects = self.paginate_queryset(projects)
        # 获取用于序列化数据的序列化器对象
        serializer = self.get_serializer(page_projects, many=True)
        # 它将序列化后的数据包装在响应中，并包含了有关分页的元信息，例如下一页、前一页等
        return self.get_paginated_response(serializer.data)

    def add(self, request):
        """
        添加项目
        :param request:
        :return:
        """
        name = request.data['name']

        if models.Project.objects.filter(name=name).first():
            response.PROJECT_EXISTS["name"] = name
            return Response(response.PROJECT_EXISTS)

            # 反序列化
        serializer = serializers.ProjectSerializer(data=request.data)

        if serializer.is_valid():
            serializer.save()
            # project = models.Project.objects.get(name)
            return Response(response.PROJECT_ADD_SUCCESS)
        response.SYSTEM_ERROR['errors'] = serializer.errors
        return Response(response.SYSTEM_ERROR)

    def update(self, request):
        """
        编辑项目
        """
        try:
            project = models.Project.objects.get(id=request.data["id"])
        except (KeyError, ObjectDoesNotExist):
            return Response(response.SYSTEM_ERROR)

        if request.data['name'] != project.name:
            if models.Project.objects.filter(name=request.data['name']).filter():
                return Response(response.PROJECT_EXISTS)
        # 调用save方法update_time字段才会自动更新
        project.name = request.data["name"]
        project.desc = request.data["desc"]
        project.responsible = request.data["responsible"]
        project.updater=request.user['username']
        project.save()
        return Response(response.PROJECT_UPDATE_SUCCESS)

    def delete(self, request):
        """
        删除项目
        """
        # if request.user.is_superuser is False:
        #     return Response(status.HTTP_401_UNAUTHORIZED)
        try:
            project = models.Project.objects.get(id=request.data["id"])
            project.delete()
            return Response(response.PROJECT_DELETE_SUCCESS)
        except ObjectDoesNotExist:
            return Response(response.SYSTEM_ERROR)

    def single(self, request, **kwargs):
        """
        得到单个项目的相关统计信息
        :param request:
        :param kwargs:
        :return:
        """

        pk = kwargs.pop('pk')
        try:
            queryset = models.Project.objects.get(id=pk)
        except ObjectDoesNotExist:
            return Response(response.PROJECT_NOT_EXISTS)

        serializer = self.get_serializer(queryset, many=False)
        project_info = prepare.get_project_detail_v2(pk)
        logger.warning(project_info)
        project_info.update(serializer.data)

        return Response(project_info)


class DashBoardView(GenericViewSet):
    """项目看板"""
    permission_classes = ()

    def get(self, request):
        _, report_status = prepare.aggregate_reports_by_status(0)
        _, report_type = prepare.aggregate_reports_by_type(0)
        report_day = prepare.aggregate_reports_or_case_bydate("day", models.Report)
        report_week = prepare.aggregate_reports_or_case_bydate("week", models.Report)
        report_month = prepare.aggregate_reports_or_case_bydate("month", models.Report)

        api_day = prepare.aggregate_apis_bydate("day")
        api_week = prepare.aggregate_apis_bydate("week")
        api_month = prepare.aggregate_apis_bydate("month")

        case_day = prepare.aggregate_reports_or_case_bydate("day", models.Case)
        case_week = prepare.aggregate_reports_or_case_bydate("week", models.Case)
        case_month = prepare.aggregate_reports_or_case_bydate("month", models.Case)

        res = {
            "report": {
                "status": report_status,
                "type": report_type,
                "week": report_week,
                "month": report_month,
                "day": report_day,
            },
            "case": {"week": case_week, "month": case_month, "day": case_day},
            "api": {"week": api_week, "month": api_month, "day": api_day},
            # 包含今天的前6天
            "recent_days": [get_day(n)[5:] for n in range(-5, 1)],
            "recent_months": [get_month_format(n) for n in range(-5, 1)],
            "recent_weeks": [get_week_format(n) for n in range(-5, 1)],
        }
        return Response(res)


class TreeView(APIView):
    """
    tree curd
    """

    authentication_classes = ()
    permission_classes = ()

    def get(self, request, **kwargs):
        """
        get tree
        create a default tree when it not exists
        """
        # 赋值对象为resp ，为StandResponse[TreeOut]类型
        type_value = request.query_params.get('type', None)
        if not type_value:
            return Response(response.SYSTEM_ERROR)
        resp: StandResponse[TreeOut] = tree_service.get_or_create(
            TreeUniqueIn(project_id=kwargs.pop("pk"), type=type_value)
        )
        return Response(resp.model_dump())

    def patch(self, request, **kwargs):
        """
        修改树形结构，ID不能重复
        """
        res = tree_service.patch(pk=kwargs["pk"], payload=TreeUpdateIn(**request.data))
        return Response(res.dict())
        # try:
        #     body = request.data["body"]
        #     mode = request.data["mode"]
        #
        #     relation = models.Relation.objects.get(id=kwargs["pk"])
        #     relation.tree = body
        #     relation.save()
        #
        # except KeyError:
        #     return Response(response.KEY_MISS)
        #
        # except ObjectDoesNotExist:
        #     return Response(response.SYSTEM_ERROR)

        #  mode -> True remove node
        # if mode:
        #     prepare.tree_end(request.data, relation.project)
        #
        # response.TREE_UPDATE_SUCCESS["tree"] = body
        # response.TREE_UPDATE_SUCCESS["max"] = get_tree_max_id(body)
        #
        # return Response(response.TREE_UPDATE_SUCCESS)


class VisitView(GenericViewSet):
    serializer_class = serializers.VisitSerializer
    queryset = models.Visit.objects

    authentication_classes = ()
    permission_classes = ()

    def list(self, request):
        project = request.query_params.get("project")
        # 查询项目前7天的访问记录
        # 根据日期分组
        # 统计每天的条数
        recent7days = [day.get_day(d)[5:] for d in range(-5, 0)]
        count_data = (
            self.get_queryset()
            .filter(
                project=project, create_time__range=(day.get_day(-5), day.get_day())
            )
            .extra(select={"create_time": "DATE_FORMAT(create_time,'%%m-%%d')"})
            .values("create_time")
            .annotate(counts=Count("id"))
            .values("create_time", "counts")
        )

        create_time_report_map = {
            data["create_time"]: data["counts"] for data in count_data
        }
        report_count = [create_time_report_map.get(d, 0) for d in recent7days]

        return Response({"recent7days": recent7days, "report_count": report_count})
